/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <cmsis_os2.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cmsis_os2.h"
#include "ohos_init.h"
#include "gpio_if.h"
#include "iot_nfc.h"

#include "ohos_init.h"
#include "iot_demo_def.h"
#include "window.h"
#include "nativeapi_config.h"
#include "wifi_sta.h"

#define max_len 128
#define CONFIG_SENSOR_SAMPLE_CYCLE 10000
#define CN_LAMP_EVENT_ALL   (CN_SWITCH_EVENT_SETSTATUS)
#define CN_SWITCH_EVENT_SETSTATUS  (1<<0)
#define CONFIG_LOCAL_TIMEZONE            8
#define CONFIG_MAX_SEND_DATA_LEN         256

static const uint16_t GPIO02 = 2;

typedef struct {
    osEventFlagsId_t switchEvent;
    bool switchSts;
    bool wifiSts;
}ApplicationController;

char g_sendMessage[CONFIG_MAX_SEND_DATA_LEN];
static ApplicationController g_appController;

#define TIMER_TICK_NUM 900

static void CtrlSetGpioLow(void)
{
    GpioSetDir(GPIO02, GPIO_DIR_OUT);
    GpioWrite(GPIO02, GPIO_VAL_LOW);
}

static void CtrlSetGpioHight(void)
{
    GpioSetDir(GPIO02, GPIO_DIR_OUT);
    GpioWrite(GPIO02, GPIO_VAL_HIGH);
}

void SetMotorSwitchSts( bool value) {
    g_appController.switchSts = value;
}

static void MotorCtrlSwitch(bool value) {
    if (value == true) {
        CtrlSetGpioHight();
    } else {
        CtrlSetGpioLow();
    }
    printf("%s:SetMotorSts=%d\r\n", __func__, g_appController.switchSts);
}

bool GetMotorSts(void) {
    return g_appController.switchSts;
}

void JsSet(bool value)
{
    SetMotorSwitchSts(value);
    osEventFlagsSet(g_appController.switchEvent, CN_SWITCH_EVENT_SETSTATUS);
}

static int JsGetClang(const char* key, char* value)
{
    if ((key == NULL) || (value == NULL)) {
        return ERROR_CODE_PARAM;
    }
    
    int length = SendDataToJs();
    printf("JsGetClang:SetValue::entry--length=%d\r\n",length);

    if (length > 0 && length < CONFIG_MAX_SEND_DATA_LEN) {
        strncpy(value, g_sendMessage, length);
        value[length] = 0;
    } else {
        printf(" JsGetClang .value = NULL\r\n");
    }

    return NATIVE_SUCCESS;
}

static int JsSetClang(const char* key, const char* value)
{
    if ((key == NULL) || (!IsValidValue(value))) {
        return ERROR_CODE_PARAM;
    }
    printf("%s : %s--%s\n", __func__, key, value);

    if(strncmp(key,"key_f1",strlen("key_f1")) == 0) {
        if(strncmp(value,"on",strlen("on")) == 0) {
            JsSet(true);
        }else {
            JsSet(false);
        }
    }
    return  NATIVE_SUCCESS;
}

bool GetWifiConnectedStatus(void) {
    /*
    struct ip_info current_ip_info;
    bwifi_get_current_ip(&current_ip_info);
    printf("current_ip :%d", current_ip_info.ip);
    */
    return CheckWifiConnectedStatus();
}

void RemoteConctol(uint32_t value) {
    /* from value to bool */
    bool option = false;
    if (value != 0 ) {
        option = true;
    }
    SetMotorSwitchSts(option);
    MotorCtrlSwitch(option);
}

int SendDataToJs(void)
{
    bool keySts = GetMotorSts();
    bool wifiSts = GetWifiConnectedStatus();

    char keyMotorStr[8];
    char wifiStsStr[16];

    if (keySts) {
        strncpy(keyMotorStr, "on", sizeof(keyMotorStr));
    } else {
        strncpy(keyMotorStr, "off", sizeof(keyMotorStr));
    }

    if (wifiSts) {
        strncpy(wifiStsStr, "connected", sizeof(wifiStsStr));
    } else {
        strncpy(wifiStsStr, "disconnected", sizeof(wifiStsStr));
    }

    g_appController.wifiSts = wifiSts;
    memset_s(g_sendMessage, CONFIG_MAX_SEND_DATA_LEN, 0, CONFIG_MAX_SEND_DATA_LEN);
    
    snprintf(g_sendMessage, sizeof(g_sendMessage),"{\"key\":\"%s\", \"wifi\":\"%s\"}", keyMotorStr, wifiStsStr);
    printf("g_sendMessage:%s.\n", g_sendMessage);

    int length = strlen(g_sendMessage);
    g_sendMessage[length] = 0;

    return length;
}

/**
 * @brief Convert miniseconds to system ticks
 * @param ms Indicates the mimiseconds to convert
 * @return Returns the corresponding ticks of specified time
 */
static uint32_t Time2Tick(uint32_t ms)
{
    uint64_t ret;
    ret = ((uint64_t)ms * osKernelGetTickFreq()) / CN_MINISECONDS_IN_SECOND;
    return (uint32_t)ret;
}

/**
 * @brief Sensor data collection task entry and the main flow is as follows:
 *        1, Wait the for the event to trigger in specified time
 *        2, Collect Sensor Data (air humidity/temperature, soil moisture, etc.)
 *        3, Report the collected data to the Cloud Platform
 */
static void MotorOperationThreadEntry(const void *arg)
{
    (void)arg;
    uint32_t waitTicks;

    waitTicks = Time2Tick(CONFIG_SENSOR_SAMPLE_CYCLE);
    printf("----------------------waitTicks:%d --------------------",waitTicks);

    while (1) {
        uint32_t switchEvent = osEventFlagsWait(g_appController.switchEvent, CN_LAMP_EVENT_ALL, osFlagsWaitAny, waitTicks);
        if (switchEvent & CN_SWITCH_EVENT_SETSTATUS) {
            printf("GetEvent:%08x", switchEvent);
            MotorCtrlSwitch(g_appController.switchSts);
            printf("Get the sensor data:switchSts:%d ", g_appController.switchSts);
        }

    }
    return;
}

void MotorOperationThread(void)
{
    printf("printf %s\r\n", __func__);
    osThreadAttr_t attr = {0};
    attr.stack_size = 1024*4;
    attr.priority = CONFIG_TASK_LEVEL;
    attr.name = "SoftbusDemoEntry";

    if (osThreadNew((osThreadFunc_t)MotorOperationThreadEntry, NULL, &attr) == NULL) {
        printf("Failed to create driver_test_task\r\n");
    }
}

static void MainTaskEntry(void *arg)
{
    int ret = 0;
    NfcInfo nfcInfo;
    char ssid[BUFF_SIZE] = {0};
    char pwd[BUFF_SIZE] = {0};

    g_appController.switchSts = false;
    MotorCtrlSwitch(g_appController.switchSts);
    g_appController.wifiSts = false;

    g_appController.switchEvent = osEventFlagsNew(NULL);
    if (g_appController.switchEvent == NULL) {
        printf("---------------------g_appController.switchEvent == NULL--------------------");
        return;
    }
    MotorOperationThread();

    printf("MainTaskEntry while\r\n");

}

void StartMainThread(void)
{
    printf("[%s:%d]: %s\n", __FILE__, __LINE__, __func__);
    JsGetClangFuncationRegister(JsGetClang);
    JsSetClangFuncationRegister(JsSetClang);
    osThreadAttr_t attr = {0};
    attr.stack_size = 1024*10;
    attr.priority = 25;
    attr.name = "window_main_entry";
    if (osThreadNew((osThreadFunc_t)MainTaskEntry, NULL, &attr) == NULL) {
        printf("Failed to create driver_test_task\r\n");
    }
}

//APP_FEATURE_INIT(StartMainThread);